# Resources: resource loading from regular file system or zipfile

import os, zipfile, os.path, StringIO
import pygame
from pygame.locals import *

CHECKENV = "Check the environment."

class Resources(object):

    zipFile = None
    zipDir = {}
    imagePath = None
    mapPath = None
    fontPath = None
    
    _dialogImage = None
    
    def __init__(self, imagedir=CHECKENV,
                       mapdir=CHECKENV,
                       fontdir=CHECKENV,
                       zipFile=None):
        l = locals()
        for path in ("image", "map", "font"):
            if l[path + "dir"] == CHECKENV:
                checkPath = "PGAME_" + path.upper() + "S"
                setattr(self, "%sPath" % path, os.environ[checkPath])
            else:
                setattr(self, "%sPath" % path, l[path + "dir"])
        
        if zipFile:
            try:
                Resources.zipFile = zipfile.ZipFile(zipFile, "rb")
            except RuntimeError:
                return
            
            for item in self.zipFile.infolist():
                self.zipDir[item.filename] = item
    
    def loadMap(self, mapName):
        fileData = None
        if self.zipFile:
            # Check the zipfile first
            zipPath = "maps/" + mapName
            if zipPath in self.zipDir:
                fileData = self.zipFile.read(zipPath)
            elif mapName in self.zipDir:
                fileData = self.zipFile.read(mapName)
        
        # Check the tiles directory
        if fileData is None:
            filePath = os.path.join(self.mapPath, mapName)
            if os.path.exists(filePath):
                fileData = file(filePath, "rU").read()
        
        if fileData is not None:
            tiles = {}
            for line in fileData.splitlines():
                x,y,v = line.split(":")
                tiles[(int(x),int(y))] = v.strip()
            return tiles
        
        return None
    
    def saveMap(self, mapName, tiles):
        # TODO: Save to zipFile        
        fMap = os.path.join(self.mapPath, mapName)
        tileData = open(fMap, "w")
        for (x,y),v in tiles:
            tileData.write("%i:%i:%s\n" % (x,y,v))
        tileData.close()
        

    
    def loadFont(self, fontName, size=12):
        fileData = None
        if self.zipFile:
            # Check the zipfile first
            zipPath = "fonts/" + fontName

            if zipPath in self.zipDir:
                fileData = self.zipFile.read(zipPath)
            elif fontName in self.zipDir:
                fileData = self.zipFile.read(fontName)
        
            if fileData is not None:
                fileObj = StringIO.StringIO(fileData)
                return pygame.font.Font(fileObj, size)

        # Check the tiles directory
        if fileData is None:
            filePath = os.path.join(self.fontPath, fontName)
            if os.path.exists(filePath):
                return pygame.font.Font(filePath, size)
        
        return None


    def loadImage(self, imageName):
        fileData = None
        if self.zipFile:
            # Check the zipfile first
            zipPath = "images/" + imageName
            if zipPath in self.zipDir:
                fileData = self.zipFile.read(zipPath)
            elif imageName in self.zipDir:
                fileData = self.zipFile.read(imageName)

        # Check the tiles directory
        if fileData is None:
            filePath = os.path.join(self.imagePath, imageName)
            if os.path.exists(filePath):
                fileData = file(filePath, "rb").read()
        
        if fileData is not None:
            fileObj = StringIO.StringIO(fileData)
            return pygame.image.load(fileObj)
        
        return None


    def renderDialog(self, width, height, seperators=()):
        if width < 32 or height < 32:
            return None
    
        if self._dialogImage is None:
            self._dialogImage = self.loadImage("dialogs.png")

        # Slice it up.
        origImage = self._dialogImage
        origSize = origImage.get_size()
        Rect = pygame.Rect
        
        topleft = origImage.subsurface(Rect(0,0,16,16))
        top = origImage.subsurface(Rect(16,0,16,16))
        sep = origImage.subsurface(Rect(16,5,16,3))
        topright = origImage.subsurface(Rect(origSize[0]-17,0,16,16))
        left = origImage.subsurface(Rect(0,16,16,16))
        center = origImage.subsurface(Rect(16,16,16,16))
        right = origImage.subsurface(Rect(origSize[0]-17,16,16,16))
        bottomleft = origImage.subsurface(Rect(0,origSize[1]-17,16,16))
        bottom = origImage.subsurface(Rect(16,origSize[1]-17,16,16))
        bottomright = origImage.subsurface(Rect(origSize[0]-17,origSize[1]-17,
                                                16,16))

        dlgImage = pygame.Surface((width,height),SRCALPHA,origImage)
        
        # Draw the corners
        dlgImage.blit(topleft, (0,0))
        dlgImage.blit(topright, (width-16,0))
        dlgImage.blit(bottomleft, (0,height-16))
        dlgImage.blit(bottomright, (width-16,height-16))
        
        # Draw the edges
        dlgImage.set_clip(Rect(16,0,width-32,height))
        for col in range((width//16)):
            dlgImage.blit(top, (col*16,0))
            dlgImage.blit(bottom, (col*16,height-16))
            
        dlgImage.set_clip(Rect(0,16,width,height-32))
        for row in range((height//16)):
            dlgImage.blit(left, (0,row*16))
            dlgImage.blit(right, (width-16,row*16))
            
        # Fill in the background.
        dlgImage.set_clip(Rect(16,16,width-32,height-32))
        for row in range((height//16)):
            for col in range((width//16)):
                dlgImage.blit(center, (col*16,row*16))
        
        # Draw the seperators
        for seprow in seperators:
            dlgImage.set_clip(Rect(6,seprow-4,width-16,seprow-1))
            for col in range(0, width-16, 16):
                dlgImage.blit(sep, (col,seprow-4))
        
            
        return dlgImage